home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / DEB / SYMS.C < prev    next >
C/C++ Source or Header  |  1994-12-12  |  19KB  |  872 lines

  1. /* This file is SYMS.C
  2. **
  3. ** changed Rainer Schnitker
  4. */
  5.  
  6. /*
  7. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  8. **
  9. ** This file is distributed under the terms listed in the document
  10. ** "copying.dj", available from DJ Delorie at the address above.
  11. ** A copy of "copying.dj" should accompany this file; if not, a copy
  12. ** should be available from where this file was obtained.  This file
  13. ** may not be distributed without a verbatim copy of "copying.dj".
  14. **
  15. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  16. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. */
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <fcntl.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <io.h>
  25. #include <memory.h>
  26. #include <malloc.h>
  27.  
  28. #ifndef __GO32__
  29. #include <sys/reg.h>
  30. #else
  31. #include <sys/_reg.h>
  32. #endif
  33.  
  34. typedef unsigned char       word8;
  35. typedef unsigned short       word16;
  36. typedef unsigned long       word32;
  37. typedef short           int16;
  38.  
  39. #include "coff.h"
  40. #include "syms.h"
  41. #include "stab.h"
  42.  
  43. extern int ptrace_get_register(int);
  44.  
  45. int undefined_symbol = 0;
  46.  
  47. struct reg_names {
  48.     char *name;
  49.     int size;
  50.     int ofs;
  51. };
  52.  
  53. struct reg_names regs[] =
  54. {
  55.   { "%eip", 4, EIP },
  56.   { "%eflags", 4, EFL },
  57.   { "%eax", 4, EAX },
  58.   { "%ebx", 4, EBX },
  59.   { "%ecx", 4, ECX },
  60.   { "%edx", 4, EDX },
  61.   { "%esp", 4, ESP },
  62.   { "%ebp", 4, EBP },
  63.   { "%esi", 4, ESI },
  64.   { "%edi", 4, EDI },
  65.   { "%ax", 2, EAX },
  66.   { "%bx", 2, EBX },
  67.   { "%cx", 2, ECX },
  68.   { "%dx", 2, EDX },
  69.   { "%ah", 0, EAX },
  70.   { "%bh", 0, EBX },
  71.   { "%ch", 0, ECX },
  72.   { "%dh", 0, EDX },
  73.   { "%al", 1, EAX },
  74.   { "%bl", 1, EBX },
  75.   { "%cl", 1, ECX },
  76.   { "%dl", 1, EDX },
  77.   { 0, 0, 0 }
  78. };
  79.  
  80. typedef struct SYM_ENTRY {
  81.   word32 string_off;
  82.   word8 type;
  83.   word8 other;
  84.   word16 desc;
  85.   word32 val;
  86. } SYM_ENTRY;
  87.  
  88. static FILHDR f_fh;
  89. static AOUTHDR f_ah;
  90. static SCNHDR *f_sh;
  91. static SYMENT *f_symtab;
  92. static SYM_ENTRY *f_aoutsyms;
  93. static AUXENT *f_aux;
  94. static LINENO **f_lnno;
  95. static char *f_string_table;
  96. static char *f_types;
  97.  
  98. /* built internally */
  99.  
  100. typedef struct {
  101.   char *filename;
  102.   word32 first_address;
  103.   word32 last_address;
  104.   LINENO *lines;
  105.   int num_lines;
  106. } FileNode;
  107.  
  108. static FileNode *files;
  109. static int num_files;
  110.  
  111. typedef struct SymNode {
  112.   char *name;
  113.   word32 address;
  114.   char type_c;
  115. } SymNode;
  116.  
  117. static SymNode *syms;
  118. static SymNode *syms_byname;
  119. static int num_syms;
  120.  
  121. static int syms_sort_bn(const void *a, const void *b)
  122. {
  123.   SymNode *sa = (SymNode *)a;
  124.   SymNode *sb = (SymNode *)b;
  125.   return strcmp(sa->name, sb->name);
  126. }
  127.  
  128. static int syms_sort_bv(const void *a, const void *b)
  129. {
  130.   SymNode *sa = (SymNode *)a;
  131.   SymNode *sb = (SymNode *)b;
  132.   return sa->address - sb->address;
  133. }
  134.  
  135. static char *symndup(char *s, int len)
  136. {
  137.   char c = s[len], *rv;
  138.   s[len] = 0;
  139.   rv = strdup(s);
  140.   s[len] = c;
  141.   return rv;
  142. }
  143.  
  144. static int valid_symbol(int i)
  145. {
  146.   char *sn;
  147.   if (f_symtab[i].e.e.e_zeroes)
  148.     sn = f_symtab[i].e.e_name;
  149.   else
  150.     sn = f_string_table + f_symtab[i].e.e.e_offset;
  151.   if (sn[0] != '_')
  152.     return 0;
  153.   if (strncmp(sn, "___gnu_compiled", 15) == 0)
  154.     return 0;
  155.   if (strcmp(sn, "__DYNAMIC") == 0)
  156.     return 0;
  157.   return 1;
  158. }
  159.  
  160. static void * xmalloc(int size)
  161. {
  162.     void *p;
  163.     if ((p = malloc(size)) == NULL) {
  164.     printf("malloc %d failed", size);
  165.     exit(1);
  166.     }
  167.     memset (p, 0, size);
  168.     return p;
  169. }
  170.  
  171. static void process_coff(FILE *fd, long ofs)
  172. {
  173.   int i, f, s, f_pending;
  174.   LINENO *l;
  175.   int l_pending;
  176.   word32 strsize;
  177.   char *name;
  178.  
  179.   fseek(fd, ofs, 0);
  180.   fread(&f_fh, 1, FILHSZ, fd);
  181.   fread(&f_ah, 1, AOUTSZ, fd);
  182.  
  183.   printf("COFF HEADER\n");
  184.   printf("text   = %08lX\n", f_ah.tsize);
  185.   printf("data   = %08lX\n", f_ah.dsize);
  186.   printf("bss    = %08lX\n", f_ah.bsize);
  187.   printf("entry  = %08lX\n", f_ah.entry);
  188.  
  189.   f_sh = (SCNHDR *)xmalloc(f_fh.f_nscns * SCNHSZ);
  190.   f_types = (char *)xmalloc(f_fh.f_nscns);
  191.   f_lnno = (LINENO **)xmalloc(f_fh.f_nscns * sizeof(LINENO *));
  192.   fread(f_sh, f_fh.f_nscns, SCNHSZ, fd);
  193.  
  194.   for (i=0; i<f_fh.f_nscns; i++)
  195.   {
  196.     if (f_sh[i].s_flags & STYP_TEXT)
  197.       f_types[i] = 'T';
  198.     if (f_sh[i].s_flags & STYP_DATA)
  199.       f_types[i] = 'D';
  200.     if (f_sh[i].s_flags & STYP_BSS)
  201.       f_types[i] = 'B';
  202.     if (f_sh[i].s_nlnno)
  203.     {
  204.       fseek(fd, ofs + f_sh[i].s_lnnoptr, 0L);
  205.       f_lnno[i] = (LINENO *)xmalloc(f_sh[i].s_nlnno * LINESZ);
  206.       fread(f_lnno[i], LINESZ, f_sh[i].s_nlnno, fd);
  207.     }
  208.     else
  209.       f_lnno[i] = 0;
  210.   }
  211.  
  212.   fseek(fd, ofs + f_fh.f_symptr + f_fh.f_nsyms * SYMESZ, 0);
  213.   fread(&strsize, 1, 4, fd);
  214.   f_string_table = (char *)xmalloc(strsize);
  215.   fread(f_string_table+4, 1, strsize-4, fd);
  216.   f_string_table[0] = 0;
  217.  
  218.   fseek(fd, ofs+f_fh.f_symptr, 0);
  219.   f_symtab = (SYMENT *)xmalloc(f_fh.f_nsyms * SYMESZ);
  220.   fread(f_symtab, SYMESZ, f_fh.f_nsyms, fd);
  221.   f_aux = (AUXENT *)f_symtab;
  222.  
  223.   num_syms = num_files = 0;
  224.   for (i=0; i<f_fh.f_nsyms; i++)
  225.   {
  226.     switch (f_symtab[i].e_sclass)
  227.     {
  228.       case C_FILE:
  229.     num_files++;
  230.     break;
  231.       case C_EXT:
  232.       case C_STAT:
  233.     if (!valid_symbol(i))
  234.       break;
  235.     num_syms++;
  236.     break;
  237.     }
  238.     i += f_symtab[i].e_numaux;
  239.   }
  240.  
  241.   files = (FileNode *)xmalloc(num_files * sizeof(FileNode));
  242.  
  243.   syms = (SymNode *)xmalloc(num_syms * sizeof(SymNode));
  244.  
  245.   f = s = f_pending = l_pending = 0;
  246.   for (i=0; i<f_fh.f_nsyms; i++)
  247.   {
  248.     switch (f_symtab[i].e_sclass)
  249.     {
  250.       case C_FILE:
  251.     if (f_aux[i+1].x_file.x_n.x_zeroes)
  252.       files[f].filename = symndup(f_aux[i+1].x_file.x_fname, 16);
  253.     else
  254.       files[f].filename = f_string_table + f_aux[i+1].x_file.x_n.x_offset;
  255.     files[f].lines = 0;
  256.     f_pending = 1;
  257.     f++;
  258.     break;
  259.       case C_EXT:
  260.       case C_STAT:
  261.  
  262.     if (f_symtab[i].e.e.e_zeroes)
  263.       name = f_symtab[i].e.e_name;
  264.     else
  265.       name = f_string_table + f_symtab[i].e.e.e_offset;
  266.  
  267.     if (f_pending && strcmp(name, ".text") == 0)
  268.     {
  269.       files[f-1].first_address = f_symtab[i].e_value;
  270.       files[f-1].last_address = f_symtab[i].e_value + f_aux[i+1].x_scn.x_scnlen - 1;
  271.       files[f-1].num_lines = f_aux[i+1].x_scn.x_nlinno;
  272.       f_pending = 0;
  273.     }
  274.  
  275.     if (ISFCN(f_symtab[i].e_type))
  276.     {
  277.       int scn = f_symtab[i].e_scnum - 1;
  278.       l = f_lnno[scn] + ((f_aux[i+1].x_sym.x_fcnary.x_fcn.x_lnnoptr - f_sh[scn].s_lnnoptr)/LINESZ);
  279.       l_pending = 1;
  280.       l->l_addr.l_paddr = f_symtab[i].e_value;
  281.     }
  282.  
  283.     if (!valid_symbol(i))
  284.       break;
  285.  
  286.     syms[s].address = f_symtab[i].e_value;
  287.     if (f_symtab[i].e.e.e_zeroes)
  288.       syms[s].name = symndup(f_symtab[i].e.e_name, 8);
  289.     else
  290.       syms[s].name = f_string_table + f_symtab[i].e.e.e_offset;
  291.  
  292.     switch (f_symtab[i].e_scnum)
  293.     {
  294.       case 1 ... 10:
  295.         syms[s].type_c = f_types[f_symtab[i].e_scnum-1];
  296.         break;
  297.       case N_UNDEF:
  298.         syms[s].type_c = 'U';
  299.         break;
  300.       case N_ABS:
  301.         syms[s].type_c = 'A';
  302.         break;
  303.       case N_DEBUG:
  304.         syms[s].type_c = 'D';
  305.         break;
  306.     }
  307.     if (f_symtab[i].e_sclass == C_STAT)
  308.       syms[s].type_c += 'a' - 'A';
  309.  
  310.     s++;
  311.     break;
  312.       case C_FCN:
  313.     if (f_pending && files[f-1].lines == 0)
  314.     {
  315.       files[f-1].lines = l;
  316.     }
  317.     if (l_pending)
  318.     {
  319.       int lbase = f_aux[i+1].x_sym.x_misc.x_lnsz.x_lnno - 1;
  320.       int i2;
  321.       l->l_lnno = lbase;
  322.       l++;
  323.       for (i2=0; l[i2].l_lnno; i2++)
  324.         l[i2].l_lnno += lbase;
  325.       l_pending = 0;
  326.     }
  327.     break;
  328.     }
  329.     i += f_symtab[i].e_numaux;
  330.   }
  331. }
  332.  
  333. #define _N_HDROFF(x)    _n_hdroff
  334. #define N_TXTOFF(x)    ( _N_HDROFF((x)) + sizeof (GNU_AOUT))
  335. #define N_DATOFF(x)    (N_TXTOFF(x)  + (x).tsize)
  336. #define N_TRELOFF(x)    (N_DATOFF(x)  + (x).dsize)
  337. #define N_DRELOFF(x)    (N_TRELOFF(x) + (x).txrel)
  338. #define N_SYMOFF(x)    (N_DRELOFF(x) + (x).dtrel)
  339. #define N_STROFF(x)    (N_SYMOFF(x)  + (x).symsize)
  340.  
  341. static void process_aout(FILE *fd, long ofs)
  342. {
  343.   GNU_AOUT header;
  344.   word32 string_table_length;
  345.   DWORD _n_hdroff;
  346.   int nsyms, i, f, s, l;
  347.  
  348.   fseek(fd, ofs, 0);
  349.   fread(&header, 1, sizeof(header), fd);
  350.  
  351.   if (header.entry == 0x10000)
  352.     _n_hdroff = (1024 - sizeof(GNU_AOUT));
  353.   else if (header.entry == 0x1020)
  354.     _n_hdroff = 0;
  355.   else {
  356.     printf("Not supported a.out file type\n");
  357.     return;
  358.   }
  359.  
  360.   printf("GNUAOUT HEADER\n");
  361.   printf("text   = %08lX\n", header.tsize);
  362.   printf("data   = %08lX\n", header.dsize);
  363.   printf("bss    = %08lX\n", header.bsize);
  364.   printf("entry  = %08lX\n", header.entry);
  365.   printf("syms   = %08lX\n", header.symsize);
  366.  
  367.   fseek(fd, ofs + N_SYMOFF(header),0);
  368.   nsyms = header.symsize / sizeof(SYM_ENTRY);
  369.   f_aoutsyms = (SYM_ENTRY *)xmalloc(header.symsize);
  370.   fread(f_aoutsyms, 1, header.symsize, fd);
  371.  
  372.   fread(&string_table_length, 1, 4, fd);
  373.   f_string_table = (char *)xmalloc(string_table_length);
  374.   fread(f_string_table+4, 1, string_table_length-4, fd);
  375.   f_string_table[0] = 0;
  376.  
  377.   num_files = num_syms = 0;
  378.   for (i=0; i<nsyms; i++)
  379.   {
  380.     char *symn = f_string_table + f_aoutsyms[i].string_off;
  381.     char *cp;
  382.     switch (f_aoutsyms[i].type & ~N_EXT)
  383.     {
  384.       case N_SO:
  385.     if (symn[strlen(symn)-1] == '/')
  386.       break;
  387.     num_files++;
  388.     break;
  389.       case N_TEXT:
  390.     cp = symn + strlen(symn) - 2;
  391.     if (strncmp(symn, "___gnu", 6) == 0 ||
  392.         strcmp(cp, "d.") == 0 /* as in gcc_compiled. */ ||
  393.         strcmp(cp, ".o") == 0)
  394.       break;
  395.       case N_DATA:
  396.       case N_ABS:
  397.       case N_BSS:
  398.       case N_FN:
  399.       case N_SETV:
  400.       case N_SETA:
  401.       case N_SETT:
  402.       case N_SETD:
  403.       case N_SETB:
  404.       case N_INDR:
  405.     num_syms ++;
  406.     break;
  407.     }
  408.   }
  409.  
  410.   syms = (SymNode *)xmalloc(num_syms * sizeof(SymNode));
  411.   memset(syms, num_syms * sizeof(SymNode), 0);
  412.   files = (FileNode *)xmalloc(num_files * sizeof(FileNode));
  413.   memset(files, num_files * sizeof(FileNode), 0);
  414.  
  415.   f = s = 0;
  416.   for (i=0; i<nsyms; i++)
  417.   {
  418.     char c, *cp;
  419.     char *symn = f_string_table + f_aoutsyms[i].string_off;
  420.     switch (f_aoutsyms[i].type & ~N_EXT)
  421.     {
  422.       case N_SO:
  423.     if (symn[strlen(symn)-1] == '/')
  424.       break;
  425.     if (f && files[f-1].last_address == 0)
  426.       files[f-1].last_address = f_aoutsyms[i].val - 1;
  427.     files[f].filename = symn;
  428.     files[f].first_address = f_aoutsyms[i].val;
  429.     f ++;
  430.     break;
  431.       case N_SLINE:
  432.     files[f-1].num_lines++;
  433.     break;
  434.       case N_TEXT:
  435.     cp = symn + strlen(symn) - 2;
  436.     if (strncmp(symn, "___gnu", 6) == 0 ||
  437.         strcmp(cp, "d.") == 0 /* as in gcc_compiled. */ ||
  438.         strcmp(cp, ".o") == 0)
  439.     {
  440.       if (f && files[f-1].last_address == 0)
  441.         files[f-1].last_address = f_aoutsyms[i].val - 1;
  442.       break;
  443.     }
  444.     c = 't';
  445.     goto sym_c;
  446.       case N_DATA:
  447.     c = 'd';
  448.     goto sym_c;
  449.       case N_ABS:
  450.     c = 'a';
  451.     goto sym_c;
  452.       case N_BSS:
  453.     c = 'b';
  454.     goto sym_c;
  455.       case N_FN:
  456.     c = 'f';
  457.     goto sym_c;
  458.       case N_SETV:
  459.     c = 'v';
  460.     goto sym_c;
  461.       case N_SETA:
  462.     c = 'v';
  463.     goto sym_c;
  464.       case N_SETT:
  465.     c = 'v';
  466.     goto sym_c;
  467.       case N_SETD:
  468.     c = 'v';
  469.     goto sym_c;
  470.       case N_SETB:
  471.     c = 'v';
  472.     goto sym_c;
  473.       case N_INDR:
  474.     c = 'i';
  475.     sym_c:
  476.     syms[s].name = symn;
  477.     syms[s].address = f_aoutsyms[i].val;
  478.     syms[s].type_c = (f_aoutsyms[i].type & N_EXT) ? (c+'A'-'a') : c;
  479.     s ++;
  480.     break;
  481.     }
  482.   }
  483.  
  484.   l = f = 0;
  485.   for (i=0; i<nsyms; i++)
  486.   {
  487.     /* char c, *cp;*/
  488.     char *symn = f_string_table + f_aoutsyms[i].string_off;
  489.     switch (f_aoutsyms[i].type & ~N_EXT)
  490.     {
  491.       case N_SO:
  492.     if (symn[strlen(symn)-1] == '/')
  493.       break;
  494.     files[f].lines = (LINENO *)xmalloc(files[f].num_lines * sizeof(LINENO));
  495.     f++;
  496.     l = 0;
  497.     break;
  498.       case N_SLINE:
  499.     files[f-1].lines[l].l_addr.l_paddr = f_aoutsyms[i].val;
  500.     files[f-1].lines[l].l_lnno = f_aoutsyms[i].desc;
  501.     l ++;
  502.     break;
  503.     }
  504.   }
  505. }
  506.  
  507. struct exe_hdr {
  508.     unsigned short signatur;
  509.     unsigned short low;
  510.     unsigned short high;
  511.     unsigned short reloc;
  512.     unsigned short hdr_para;
  513. };
  514.  
  515. struct emx_hdr {
  516.     char sig[18];
  517.     char next_off[4];
  518. };
  519.  
  520. int skip_exe_hdr(FILE *fd, unsigned long *headoff)
  521. {
  522.     struct exe_hdr exehdr;
  523.     struct emx_hdr emxhdr;
  524.     *headoff=0;
  525.  
  526.     fseek(fd, 0, 0);
  527.     fread(&exehdr, sizeof(struct exe_hdr), 1, fd);
  528.  
  529.     if (exehdr.signatur == 0x5a4d) {
  530.     *headoff = ((unsigned long) exehdr.hdr_para) * 16;
  531.     fseek(fd, *headoff, 0);
  532.     fread(&emxhdr, sizeof(struct emx_hdr), 1, fd);
  533.     if (memcmp(emxhdr.sig, "emx", 3) == 0)
  534.         *headoff = *(int *) emxhdr.next_off;
  535.     else {        /* not a emx file */
  536.         long new_off;
  537.  
  538.         fseek(fd, 0x3C, SEEK_SET);
  539.         fread(&new_off, sizeof(long), 1, fd);
  540.         if (new_off) {
  541.         char pe_sig[4];
  542.         fseek(fd, new_off, SEEK_SET);
  543.         fread(pe_sig, sizeof(pe_sig), 1, fd);
  544.         printf("file is a new executable '%c%c'", pe_sig[0], pe_sig[1]);
  545.         if (pe_sig[0]) {
  546.             *headoff = new_off + 4;
  547.         }
  548.         }
  549.         else { /* djgpp */
  550.         *headoff = (DWORD) exehdr.high * 512L;
  551.         if (exehdr.low)
  552.             *headoff += (DWORD) exehdr.low - 512L;
  553.         }
  554.     }
  555.     }
  556.     if (!fseek(fd, *headoff, 0))
  557.     return 0;
  558.     else {
  559.     *headoff = 0;
  560.     fseek(fd, 0, 0);
  561.     return -1;
  562.     }
  563. }
  564.  
  565. static void process_file(FILE *fd, long ofs)
  566. {
  567.   short s;
  568.   skip_exe_hdr(fd, &ofs);
  569.   fread(&s, 2, 1, fd);
  570.  
  571.   switch (s)
  572.   {
  573.     case 0x014c:    /* .coff */
  574.       process_coff(fd, ofs);
  575.       break;
  576.     case 0x010b:    /* a.out ZMAGIC */
  577.     case 0x0107:    /* a.out object */
  578.       process_aout(fd, ofs);
  579.       break;
  580.   }
  581. }
  582.  
  583. void syms_init(char *fname)
  584. {
  585.   FILE *fd = fopen(fname, "rb");
  586.   if (fd == 0)
  587.   {
  588.     perror(fname);
  589.   }
  590.   else
  591.   {
  592.     process_file(fd, 0);
  593.  
  594.     syms_byname = (SymNode *)xmalloc(num_syms * sizeof(SymNode));
  595.     memcpy(syms_byname, syms, num_syms * sizeof(SymNode));
  596.     qsort(syms_byname, num_syms, sizeof(SymNode), syms_sort_bn);
  597.     qsort(syms, num_syms, sizeof(SymNode), syms_sort_bv);
  598.  
  599.     fclose(fd);
  600.   }
  601. }
  602.  
  603. int lookup_sym_byname(char *name, int idx, int ofs)
  604. {
  605.   int below, above;
  606.   char ch = name[idx];
  607.   name[idx] = 0;
  608.  
  609.   below = -1;
  610.   above = num_syms;
  611.   while (above - below > 1)
  612.   {
  613.     int mid = (above + below) / 2;
  614.     int c = 0;
  615.     if (ofs)
  616.       c = '_' - syms_byname[mid].name[0];
  617.     if (c == 0)
  618.       c = strcmp(name, syms_byname[mid].name+ofs);
  619.     if (c == 0)
  620.     {
  621.       name[idx] = ch;
  622.       return mid;
  623.     }
  624.     if (c < 0)
  625.       above = mid;
  626.     else
  627.       below = mid;
  628.   }
  629.   name[idx] = ch;
  630.   return -1;
  631. }
  632.  
  633. word32 syms_name2val(char *name)
  634. {
  635.   int idx, sign=1, i;
  636.   word32 v,pt;
  637.   char *cp;
  638.  
  639.   undefined_symbol = 0;
  640.  
  641.   idx = 0;
  642.   sscanf(name, "%s", name);
  643.  
  644.   if (name[0] == 0)
  645.     return 0;
  646.  
  647.   if (name[0] == '-')
  648.   {
  649.     sign = -1;
  650.     name++;
  651.   }
  652.   else if (name[0] == '+')
  653.   {
  654.     name++;
  655.   }
  656.   if (isdigit(name[0]))
  657.   {
  658.     if (sign == -1)
  659.       return -strtol(name, 0, 0);
  660.     return strtol(name, 0, 0);
  661.   }
  662.  
  663.   cp = strpbrk(name, "+-");
  664.   if (cp)
  665.     idx = cp-name;
  666.   else
  667.     idx = strlen(name);
  668.  
  669.   if (name[0] == '%') /* register */
  670.   {
  671.     for (i=0; regs[i].name; i++)
  672.       if (strncmp(name, regs[i].name, idx) == 0)
  673.       {
  674.     pt = ptrace_get_register(regs[i].ofs * 4);
  675.     switch (regs[i].size)
  676.     {
  677.       case 0: /* ah */
  678.         v = (pt>>8) & 0xFF;
  679.         break;
  680.       case 1: /* al */
  681.         v = pt & 0xFF;
  682.         break;
  683.       case 2: /* ax */
  684.         v = pt & 0xFFFF;
  685.         break;
  686.       case 4: /* eax */
  687.         v = pt;
  688.         break;
  689.     }
  690.     return v + syms_name2val(name+idx);
  691.       }
  692.   }
  693.  
  694.   for (i=0; i<idx; i++)
  695.     if (name[i] == '#')
  696.     {
  697.       int f;
  698.       int lnum, l;
  699.       sscanf(name+i+1, "%d", &lnum);
  700.       for (f=0; f<num_files; f++)
  701.       {
  702.     if ((strncmp(name, files[f].filename, i) == 0) && (files[f].filename[i] == 0))
  703.     {
  704.       for (l=0; l<files[f].num_lines; l++)
  705.       {
  706.         if (files[f].lines[l].l_lnno == lnum)
  707.           return files[f].lines[l].l_addr.l_paddr + syms_name2val(name+idx);
  708.       }
  709.       printf("undefined line number %.*s\n", idx, name);
  710.       undefined_symbol = 1;
  711.       return 0;
  712.     }
  713.       }
  714.       printf("Undefined file name %.*s\n", i, name);
  715.       undefined_symbol = 1;
  716.       return 0;
  717.     }
  718.  
  719.   i = lookup_sym_byname(name, idx, 0);
  720.   if (i == -1)
  721.     i = lookup_sym_byname(name, idx, 1);
  722.   if (i != -1)
  723.     return syms_byname[i].address * sign + syms_name2val(name+idx);
  724.   printf("Undefined symbol %.*s\n", idx, name);
  725.   undefined_symbol = 1;
  726.   return 0;
  727. }
  728.  
  729. static char noname_buf[11];
  730.  
  731. char *syms_val2name(word32 val, word32 *delta)
  732. {
  733.   /* static char buf[1000];*/
  734.   int above, below, mid;
  735.  
  736.   if (delta)
  737.     *delta = 0;
  738.  
  739.   if (num_syms <= 0)
  740.     goto noname;
  741.   above = num_syms;
  742.   below = -1;
  743.   while (above-below > 1)
  744.   {
  745.     mid = (above+below)/2;
  746.     if (syms[mid].address == val)
  747.       break;
  748.     if (syms[mid].address > val)
  749.       above = mid;
  750.     else
  751.       below = mid;
  752.   }
  753.   if (syms[mid].address > val)
  754.   {
  755.     if (mid == 0)
  756.       goto noname;
  757.     mid--; /* the last below was it */
  758.   }
  759.   if (mid < 0)
  760.     goto noname;
  761.   if (strcmp(syms[mid].name, "_end") == 0)
  762.     goto noname;
  763.   if (strcmp(syms[mid].name, "__end") == 0)
  764.     goto noname;
  765.   if (strcmp(syms[mid].name, "_etext") == 0)
  766.     goto noname;
  767.   if (delta)
  768.     *delta = val - syms[mid].address;
  769.   return syms[mid].name;
  770. noname:
  771.   sprintf(noname_buf, "%#lx", val);
  772.   return noname_buf;
  773. }
  774.  
  775. char *syms_val2line(word32 val, int *lineret, int exact)
  776. {
  777.   int f, l;
  778.   for (f=0; f<num_files; f++)
  779.   {
  780.     if (val >= files[f].first_address && val <= files[f].last_address && files[f].lines)
  781.     {
  782.       for (l=files[f].num_lines-1; l >= 0 && files[f].lines[l].l_addr.l_paddr > val; l--);
  783.       if ((files[f].lines[l].l_addr.l_paddr != val) && exact)
  784.     return 0;
  785.       *lineret = files[f].lines[l].l_lnno;
  786.       return files[f].filename;
  787.     }
  788.   }
  789.   return 0;
  790. }
  791.  
  792. int wild(char *pattern, char *string)
  793. {
  794.   int nlit;
  795.   while (*pattern)
  796.   {
  797.     switch (*pattern)
  798.     {
  799.       case '*':
  800.     pattern++;
  801.     if (*pattern == 0)
  802.       return 1;
  803.     nlit=0;
  804.     while ((pattern[nlit] != 0)
  805.         && (pattern[nlit] != '*')
  806.         && (pattern[nlit] != '?') )
  807.       nlit++;
  808.     while (1)
  809.     {
  810.       if (strncmp(string, pattern, nlit) == 0)
  811.         break;
  812.       string++;
  813.       if (*string == 0)
  814.         return 0;
  815.     }
  816.     break;
  817.       case '?':
  818.     if (*string == 0)
  819.       return 0;
  820.     pattern++;
  821.     string++;
  822.     break;
  823.       default:
  824.     if (*pattern != *string)
  825.       return 0;
  826.     pattern++;
  827.     string++;
  828.     break;
  829.     }
  830.   }
  831.   if (*string)
  832.     return 0;
  833.   return 1;
  834. }
  835.  
  836. void syms_listwild(char *pattern)
  837. {
  838.   int linecnt = 0;
  839.   int lnum;
  840.   char *name;
  841.   int i, key;
  842.  
  843.   for (i=0; i<num_syms; i++)
  844.     if (wild(pattern, syms_byname[i].name))
  845.     {
  846.       if (++linecnt > 20)
  847.       {
  848.     printf("--- More ---");
  849.     fflush(stdout);
  850.     key = getchar();
  851.     printf("\r            \r");
  852.     switch (key)
  853.     {
  854.       case ' ':
  855.         linecnt = 0;
  856.         break;
  857.       case 13:
  858.         linecnt--;
  859.         break;
  860.       case 'q':
  861.       case 27:
  862.         return;
  863.     }
  864.       }
  865.       printf("0x%08lx %c %s", syms_byname[i].address, syms_byname[i].type_c, syms_byname[i].name);
  866.       name = syms_val2line(syms_byname[i].address, &lnum, 0);
  867.       if (name)
  868.     printf(", line %d of %s", lnum, name);
  869.       putchar('\n');
  870.     }
  871. }
  872.